{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5d904dee",
   "metadata": {},
   "source": [
    "# Example 7: Solving Partial Differential Equation (PDE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d568912",
   "metadata": {},
   "source": [
    "We aim to solve a 2D poisson equation $\\nabla^2 f(x,y) = -2\\pi^2{\\rm sin}(\\pi x){\\rm sin}(\\pi y)$, with boundary condition $f(-1,y)=f(1,y)=f(x,-1)=f(x,1)=0$. The ground truth solution is $f(x,y)={\\rm sin}(\\pi x){\\rm sin}(\\pi y)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0e2bc449",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "cuda\n",
      "checkpoint directory created: ./model\n",
      "saving model version 0.0\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "pde loss: 2.13e+00 | bc loss: 1.80e-03 | l2: 3.11e-03 : 100%|███████| 50/50 [00:35<00:00,  1.43it/s]\n",
      "pde loss: 5.68e-01 | bc loss: 5.30e-04 | l2: 1.03e-03 : 100%|███████| 50/50 [00:35<00:00,  1.43it/s]\n",
      "pde loss: 1.23e-01 | bc loss: 1.51e-04 | l2: 1.74e-04 : 100%|███████| 50/50 [00:35<00:00,  1.42it/s]\n"
     ]
    }
   ],
   "source": [
    "from kan import KAN, LBFGS\n",
    "import torch\n",
    "import matplotlib.pyplot as plt\n",
    "from torch import autograd\n",
    "from tqdm import tqdm\n",
    "\n",
    "device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n",
    "print(device)\n",
    "\n",
    "\n",
    "dim = 2\n",
    "np_i = 51 # number of interior points (along each dimension)\n",
    "np_b = 51 # number of boundary points (along each dimension)\n",
    "ranges = [-1, 1]\n",
    "\n",
    "\n",
    "def batch_jacobian(func, x, create_graph=False):\n",
    "    # x in shape (Batch, Length)\n",
    "    def _func_sum(x):\n",
    "        return func(x).sum(dim=0)\n",
    "    return autograd.functional.jacobian(_func_sum, x, create_graph=create_graph).permute(1,0,2)\n",
    "\n",
    "# define solution\n",
    "sol_fun = lambda x: torch.sin(torch.pi*x[:,[0]])*torch.sin(torch.pi*x[:,[1]])\n",
    "source_fun = lambda x: -2*torch.pi**2 * torch.sin(torch.pi*x[:,[0]])*torch.sin(torch.pi*x[:,[1]])\n",
    "\n",
    "# interior\n",
    "sampling_mode = 'mesh' # 'radnom' or 'mesh'\n",
    "\n",
    "x_mesh = torch.linspace(ranges[0],ranges[1],steps=np_i)\n",
    "y_mesh = torch.linspace(ranges[0],ranges[1],steps=np_i)\n",
    "X, Y = torch.meshgrid(x_mesh, y_mesh, indexing=\"ij\")\n",
    "if sampling_mode == 'mesh':\n",
    "    #mesh\n",
    "    x_i = torch.stack([X.reshape(-1,), Y.reshape(-1,)]).permute(1,0)\n",
    "else:\n",
    "    #random\n",
    "    x_i = torch.rand((np_i**2,2))*2-1\n",
    "    \n",
    "x_i = x_i.to(device)\n",
    "\n",
    "# boundary, 4 sides\n",
    "helper = lambda X, Y: torch.stack([X.reshape(-1,), Y.reshape(-1,)]).permute(1,0)\n",
    "xb1 = helper(X[0], Y[0])\n",
    "xb2 = helper(X[-1], Y[0])\n",
    "xb3 = helper(X[:,0], Y[:,0])\n",
    "xb4 = helper(X[:,0], Y[:,-1])\n",
    "x_b = torch.cat([xb1, xb2, xb3, xb4], dim=0)\n",
    "\n",
    "x_b = x_b.to(device)\n",
    "\n",
    "alpha = 0.01\n",
    "log = 1\n",
    "\n",
    "\n",
    "grids = [5,10,20]\n",
    "steps = 50\n",
    "\n",
    "pde_losses = []\n",
    "bc_losses = []\n",
    "l2_losses = []\n",
    "\n",
    "for grid in grids:\n",
    "    if grid == grids[0]:\n",
    "        model = KAN(width=[2,2,1], grid=grid, k=3, seed=1, device=device)\n",
    "        model = model.speed()\n",
    "    else:\n",
    "        model.save_act = True\n",
    "        model.get_act(x_i)\n",
    "        model = model.refine(grid)\n",
    "        model = model.speed()\n",
    "\n",
    "    def train():\n",
    "        optimizer = LBFGS(model.parameters(), lr=1, history_size=10, line_search_fn=\"strong_wolfe\", tolerance_grad=1e-32, tolerance_change=1e-32, tolerance_ys=1e-32)\n",
    "\n",
    "        pbar = tqdm(range(steps), desc='description', ncols=100)\n",
    "\n",
    "        for _ in pbar:\n",
    "            def closure():\n",
    "                global pde_loss, bc_loss\n",
    "                optimizer.zero_grad()\n",
    "                # interior loss\n",
    "                sol = sol_fun(x_i)\n",
    "                sol_D1_fun = lambda x: batch_jacobian(model, x, create_graph=True)[:,0,:]\n",
    "                sol_D1 = sol_D1_fun(x_i)\n",
    "                sol_D2 = batch_jacobian(sol_D1_fun, x_i, create_graph=True)[:,:,:]\n",
    "                lap = torch.sum(torch.diagonal(sol_D2, dim1=1, dim2=2), dim=1, keepdim=True)\n",
    "                source = source_fun(x_i)\n",
    "                pde_loss = torch.mean((lap - source)**2)\n",
    "\n",
    "                # boundary loss\n",
    "                bc_true = sol_fun(x_b)\n",
    "                bc_pred = model(x_b)\n",
    "                bc_loss = torch.mean((bc_pred-bc_true)**2)\n",
    "\n",
    "                loss = alpha * pde_loss + bc_loss\n",
    "                loss.backward()\n",
    "                return loss\n",
    "\n",
    "            if _ % 5 == 0 and _ < 20:\n",
    "                model.update_grid_from_samples(x_i)\n",
    "\n",
    "            optimizer.step(closure)\n",
    "            sol = sol_fun(x_i)\n",
    "            loss = alpha * pde_loss + bc_loss\n",
    "            l2 = torch.mean((model(x_i) - sol)**2)\n",
    "\n",
    "            if _ % log == 0:\n",
    "                pbar.set_description(\"pde loss: %.2e | bc loss: %.2e | l2: %.2e \" % (pde_loss.cpu().detach().numpy(), bc_loss.cpu().detach().numpy(), l2.cpu().detach().numpy()))\n",
    "\n",
    "            pde_losses.append(pde_loss.cpu().detach().numpy())\n",
    "            bc_losses.append(bc_loss.cpu().detach().numpy())\n",
    "            l2_losses.append(l2.cpu().detach().numpy())\n",
    "            \n",
    "        \n",
    "    train()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "dcbfa677",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.legend.Legend at 0x7f94ac3c5cd0>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(pde_losses, marker='o')\n",
    "plt.plot(bc_losses, marker='o')\n",
    "plt.plot(l2_losses, marker='o')\n",
    "plt.yscale('log')\n",
    "plt.xlabel('steps')\n",
    "plt.legend(['PDE loss', 'BC loss', 'L2 squared'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bce40477",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
